/**
 * @format
 * @Author: TC
 * @Date: 2023-04-03 23:08:50
 * @Last Modified by: TC
 * @Last Modified time: 2023-08-20 14:32:19
 */

import { _decorator, Enum, instantiate, Node, Prefab, ScrollView, Size, UITransform, v2, v3, Vec2 } from "cc";
import { app } from "../../App";
import { mFrameEnumConst } from "../../Const/FrameEnumConst";

const { ccclass, property } = _decorator;

@ccclass("VirtualScrollView")
export class VirtualScrollView extends ScrollView {
    @property({ type: Enum(mFrameEnumConst.LOYOUT_TYPE), displayName: "排列格式" })
    layoutType: mFrameEnumConst.LOYOUT_TYPE = mFrameEnumConst.LOYOUT_TYPE.VERTICAL;
    @property({ type: Prefab, displayName: "单元预制" })
    preItem: Prefab = null;

    private _itemCnt: number = 0;

    private _itemClone: Node = null; //预制实例
    private _itemWidth: number = 0; //单元宽度
    private _itemHeight: number = 0; //单元高度
    private _maxCount: number = 0; //最大显示个数
    private _startIndex: number = 0; //开始索引
    private _endIndex: number = 0; //结束索引
    private _viewSize: Size = null; //可视区域尺寸
    private _perOffset: Vec2 = v2(); //上一次刷新时的坐标偏移
    private _itemAnchorPoint: Vec2 = v2(); //单元锚点

    private _onRender: (index: number, item: Node) => void; //渲染回调

    onLoad(): void {
        this._viewSize = this.view.contentSize;
        this._itemClone = instantiate(this.preItem);
        this._itemAnchorPoint = this._itemClone.getComponent(UITransform).anchorPoint;
        app.timerMgr.schedule(this.onUpdate, this, null, 0, -1);
    }

    public setListData(dataList: any[], cb: (index: number, item: Node) => void): void {
        this._itemCnt = dataList.length;
        this.content.removeAllChildren();
        this._itemWidth = this._itemClone.getComponent(UITransform).width;
        this._itemHeight = this._itemClone.getComponent(UITransform).height;
        this.resetContent();
        this._onRender = cb;
        this.onUpdate(true);
    }

    /**
     * 重置内容
     */
    private resetContent(): void {
        this.content.getComponent(UITransform).height = this._itemCnt * this._itemHeight;
        this._maxCount = Math.min(this._itemCnt, Math.floor(this._viewSize.height / this._itemHeight) + 2);
        for (let i = 0; i < this._maxCount; i++) {
            let node = instantiate(this.preItem);
            node.setPosition(v3(this._itemWidth / 2, -this._itemHeight / 2 - i * this._itemHeight, 0));
            this.content.addChild(node);
        }
        // this.stopAutoScroll();
        // this.scrollToOffset(v2(), 0);
    }

    /**
     * 是否需要刷新
     * @returns
     */
    private needUpdate(): boolean {
        if (!this._onRender) {
            return false;
        }
        let currOffset = this.getScrollOffset();
        if (0 === Vec2.distance(currOffset, this._perOffset)) {
            return false;
        }
        return true;
    }

    private onUpdate(force: boolean = false): void {
        if (!this.needUpdate() && !force) {
            return;
        }
        this._perOffset = this.getScrollOffset();

        let currOffset = this.getScrollOffset();
        this._startIndex = Math.floor(currOffset.y / this._itemHeight);
        this._endIndex = this._startIndex + this._maxCount;
        let firstY: number = -this._itemHeight * this._itemAnchorPoint.y - this._startIndex * this._itemHeight;
        //计算可视节点位置并渲染
        for (let index = this._startIndex; index < this._endIndex; index++) {
            let childrenIndex = index - this._startIndex;
            let node = this.content.children[childrenIndex];
            if (index < this._itemCnt && index >= 0) {
                node.setPosition(v3(this._itemWidth * this._itemAnchorPoint.x, firstY - childrenIndex * this._itemHeight));
                this._onRender(index, node);
            } else {
                node.setPosition(v3(-this._itemWidth * this._itemAnchorPoint.x, 0));
            }
        }
    }

    /**
     * 清空
     */
    public clean(): void {
        this.setListData([], null);
    }
}
